#include <iostream>

#include "../support/Threading.hpp"
#include "Externs.hpp"

#include <swarm/type_setup.h>
#include <swarm/Locale.h>
#include <swarm/Latch.h>
#include <swarm/Bool.h>
#include <swarm/Runtime.h>
#include <swarm/Resource.h>
#include <swarm/Scheduler.h>
#include <swarm/Env.h>
#include <swarm/Identifiable.h>
#include <swarm/util/atomic.h>


swarm_CodeletDesc_IMPL_NOCANCEL_NOCAST(initialize_once, initialize_once, swarm_c_void, swarm_c_void)
int i, j, k;

int SLABS = 2;
int ARRAY_SIZE = Npadded * Npadded * Npadded;

#ifndef STATIC_ALLOC
std::cerr << "Starting Alloc\n";

A = (double (*)[2][Npadded][Npadded][Npadded]) malloc (SLABS * ARRAY_SIZE * sizeof(double));
Acheck = (double (*)[2][Npadded][Npadded][Npadded]) malloc (SLABS * ARRAY_SIZE * sizeof(double));
#endif // STATIC_ALLOC

double d = 0.0; // used for template instantiation
Threading::pinPages(A, SLABS, ARRAY_SIZE, d);

// Rand not thread safe, separate from init of A
for (i = 0; i < Npadded; i++) {
  for (j = 0; j < Npadded; j++) {
    for (k = 0; k < Npadded; k++) {
      Acheck[0][0][i][j][k] = 0.0;//(double)(rand() / ((double)RAND_MAX + 1));
      Acheck[0][1][i][j][k] = 0.0;//(double)(rand() / ((double)RAND_MAX + 1));
    }
  }
}

// Just set 100 random values in each array
for (i=0; i<100; i++) {
  Acheck[0][0][rand() % Npadded][rand() % Npadded][rand() % Npadded] =
    1000.0 * (double)(rand() / ((double)RAND_MAX + 1));
  Acheck[0][1][rand() % Npadded][rand() % Npadded][rand() % Npadded] =
    1000.0 * (double)(rand() / ((double)RAND_MAX + 1));
}

for (i = 0; i < Npadded; i++) {
  for (j = 0; j < Npadded; j++) {
    for (k = 0; k < Npadded; k++) {
      A[0][0][i][j][k] = Acheck[0][0][i][j][k];
      A[0][1][i][j][k] = Acheck[0][1][i][j][k];
    }
  }
}

finished_initialization = 1;
pthread_cond_signal(&initialization_cv);
swarm_CodeletDesc_IMPL_END;
